package com.zrkizzy.generator.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zrkizzy.common.core.constant.HttpConst;
import com.zrkizzy.common.core.domain.response.PageResult;
import com.zrkizzy.generator.dto.GenerateOptionDTO;
import com.zrkizzy.generator.mapper.GenerateMapper;
import com.zrkizzy.generator.query.GenerateQuery;
import com.zrkizzy.generator.service.IGenerateService;
import com.zrkizzy.generator.util.FreemarkerUtil;
import com.zrkizzy.generator.util.GenerateUtil;
import com.zrkizzy.generator.vo.TableDataVO;
import freemarker.template.Configuration;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 代码生成业务逻辑接口实现类
 *
 * @author zhangrongkang
 * @since 2024/1/11
 */
@Slf4j
@Service
public class GenerateServiceImpl implements IGenerateService {

    @Autowired
    private GenerateUtil generateUtil;

    @Autowired
    private GenerateMapper generateMapper;

    /**
     * 分页获取数据库表格
     *
     * @param generateQuery 代码生成查询对象
     * @return 表格分页数据
     */
    @Override
    public PageResult<TableDataVO> listTable(GenerateQuery generateQuery) {
        Page<TableDataVO> page = new Page<>(generateQuery.getCurrentPage(), generateQuery.getPageSize());
        // 查询到所有数据，手动分页
        Page<TableDataVO> list = generateMapper.listTable(page, generateQuery);
        // 数据总数
        return PageResult.<TableDataVO>builder()
                .list(list.getRecords())
                .total(list.getTotal()).build();
    }

    /**
     * 预览代码
     *
     * @param generateOptionDTO 代码生成选项数据传输对象
     * @return 生成代码内容
     */
    @Override
    public Map<String, String> preview(GenerateOptionDTO generateOptionDTO) {
        Map<String, String> result = new HashMap<>();
        // 设置代码生成参数
        Map<String, Object> map = setGenerateAttribute(generateOptionDTO);
        // 获取要生成的模板列表
        List<String> templateList = FreemarkerUtil.getTemplateList();
        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        for (String template : templateList) {
            String templateLoading = FreemarkerUtil.getTemplateLoading(template);
            configuration.setClassForTemplateLoading(this.getClass(), templateLoading);
            String ftl = FreemarkerUtil.getTemplateName(template);
            try {
                String content = FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate(ftl), map);
                result.put(ftl.replace(".ftl", ""), content);
            } catch (Exception e) {
                log.info("生成代码出错, e: {}", e.getMessage());
            }
        }
        return result;
    }

    /**
     * 下载代码
     *
     * @param generateOptionDTO 代码生成选项数据传输对象
     * @return 生成代码 byte[] 内容
     */
    @Override
    public byte[] download(GenerateOptionDTO generateOptionDTO) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);

        // 设置代码生成参数
        Map<String, Object> map = setGenerateAttribute(generateOptionDTO);
        // 获取要生成的模板列表
        List<String> templateList = FreemarkerUtil.getTemplateList();
        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        for (String template : templateList) {
            String templateLoading = FreemarkerUtil.getTemplateLoading(template);
            configuration.setClassForTemplateLoading(this.getClass(), templateLoading);
            String ftl = FreemarkerUtil.getTemplateName(template);
            try {
                String content = FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate(ftl), map);
                // 添加到Zip
                zip.putNextEntry(new ZipEntry(ftl.replace(".ftl", "")));
                IOUtils.write(content, zip, HttpConst.UTF_8);
                zip.flush();
                zip.closeEntry();
            } catch (Exception e) {
                log.error("下载代码出错, e: {}", e.getMessage());
            }
        }
        IOUtils.closeQuietly(zip);

        return outputStream.toByteArray();
    }

    /**
     * 设置代码生成参数
     *
     * @param generateOptionDTO 代码生成选项数据
     * @return 代码生成参数
     */
    private Map<String, Object> setGenerateAttribute(GenerateOptionDTO generateOptionDTO) {
        Map<String, Object> map = new HashMap<>();
        // 设置包路径参数
        generateUtil.setPackageAttribute(generateOptionDTO, map);
        // 设置请求类参数
        generateUtil.setClassAttribute(generateOptionDTO, map);
        // 设置字段参数
        generateUtil.setFieldAttribute(generateOptionDTO, map);
        return map;
    }

}
